package com.wangwen.wechatmp.utils;


import com.alibaba.fastjson.JSONObject;
import com.wangwen.wechatmp.dao.ConfWxmpDao;
import com.wangwen.wechatmp.dao.UserInfoDao;
import com.wangwen.wechatmp.dao.UserIntegralDao;
import com.wangwen.wechatmp.entity.ApiResponse;
import com.wangwen.wechatmp.exception.RuntimeCheck;
import com.wangwen.wechatmp.model.ConfWxmp;
import com.wangwen.wechatmp.model.UserInfo;
import com.wangwen.wechatmp.model.UserIntegral;
import com.wangwen.wechatmp.wxpkg.config.WxMpConfiguration;
import com.wangwen.wechatmp.entity.ApiResponse;
import com.wangwen.wechatmp.exception.RuntimeCheck;
import com.wangwen.wechatmp.model.ConfWxmp;
import com.wangwen.wechatmp.wxpkg.config.WxMpConfiguration;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpCardService;
import me.chanjar.weixin.mp.api.WxMpService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by wangwei on 16/9/5.
 */
@Component
public class WechatUtils {

    @Value("${wechat.appId}")
    private String appId;

    @Value("${wechat.secret}")
    private String secret;


    @Value("${wechat.cardId}")
    private String cardId;

    @Autowired
    private ConfWxmpDao confWxmpDao;
    /**
     * 获取在该公众号下的用户会员卡信息
     * @return
     */
    private static final String  GET_CARD_LIST = "https://api.weixin.qq.com/card/user/getcardlist";
    /**
     * 获取用户会员卡信息
     * @return
     */
    private static final String  GET_USER_INFO = "https://api.weixin.qq.com/card/membercard/userinfo/get";

    /**
     * 更新用户会员卡信息
     * @return
     */
    private static final String  UPDATE_USER_INFO = "https://api.weixin.qq.com/card/membercard/updateuser";

    @Autowired
    private UserInfoDao userInfoDao;

    @Autowired
    private UserIntegralDao userIntegralDao;

    protected Logger logger = LoggerFactory.getLogger(getClass());


    public  String getNoncestr() {
        String str = "";
        // 循环得到10个字母
        for (int i = 0; i < 10; i++) {
            // 得到随机字母
            char c = (char) ((Math.random() * 26) + 97);
            // 拼接成字符串
            str += (c + "");
        }
        return str;
    }

    public String getOpenid(Integer busId,String code){
        ConfWxmp confWxmp = confWxmpDao.findByBusId(busId);
        RuntimeCheck.ifNull(confWxmp,"该酒店信息未配置");

        logger.info("code----------"+code,"appId-----"+confWxmp.getAppId(),"secret-----"+confWxmp.getSecret());
        String result = HttpUtil
                .get("https://api.weixin.qq.com/sns/oauth2/access_token?appid="
                        + confWxmp.getAppId()
                        + "&secret="
                        + confWxmp.getSecret()
                        + "&code="
                        + code
                        + "&grant_type=authorization_code");
        Map<?, ?> bean = JsonUtil.toBean(result, Map.class);
        if(bean.get("openid") == null){
            logger.info("返回openid----------null");
//            throw new RuntimeException("没有获取到openid,请检查");
            return null;
        }
        logger.info("--------------返回openid"+bean.get("openid").toString());
        return bean.get("openid").toString();
    }



    /**
     * 修改积分信息
     */
    public ApiResponse<String> upWeiXinScore(Integer hotelId,String cardId,String code,Integer bonus, Integer addBonus,String remark ) {

        try {
            JSONObject jsonParam = new JSONObject();
            jsonParam.put("card_id", cardId);
            jsonParam.put("code",code);
            jsonParam.put("bonus",bonus);
            jsonParam.put("add_bonus",addBonus);
            jsonParam.put("record_bonus",remark);//消费类型
            String param = jsonParam.toJSONString();
            logger.info("upWeiXinScore----------请求参数---------"+param);

            WxMpService wxMpService = this.getMpService(hotelId);

            String result = wxMpService.post(UPDATE_USER_INFO,param);
            Map resultMap = JsonUtil.toMap(result);
            if((int)resultMap.get("errcode") == 0){
                return ApiResponse.success("微信积分更新成功！");
            }

        } catch (WxErrorException e) {
            logger.error("-------------微信积分更新接口调用失败------------", e);
            e.printStackTrace();
            return ApiResponse.fail("微信积分更新接口调用失败");
        }
        return null;
    }

    /**
     * 获取微信用户信息   保存到本地
     * @return
     */
    public ApiResponse<Map<String,String>> getUserInfo(Integer hotelId,String cardId,String code){
        try {
            JSONObject jsonParam = new JSONObject();
            jsonParam.put("card_id", cardId);
            jsonParam.put("code",code);
            String param = jsonParam.toJSONString();
            System.out.println(param);
            logger.info("getUserInfo----------请求参数---------"+param);
            WxMpService wxMpService = this.getMpService(hotelId);
            String result = wxMpService.post(GET_USER_INFO,param);
            Map resultMap = JsonUtil.toMap(result);
            if((int)resultMap.get("errcode") == 0){
                    //开启新的线程保存用户信息
                    new Thread(() ->{
                        saveUserInfo(hotelId,cardId,code,resultMap);
                    }).start();

                return ApiResponse.success(resultMap);
            }

        } catch (WxErrorException e) {
            logger.error("微信接口获取用户会员信息有误",e);
            return ApiResponse.fail(new HashMap<String,String>());
        }
        return null;
    }

    /**
     * 从微信返回结果中拉取数据
     * @param hotelId
     * @param cardId
     * @param code
     * @param resultMap
     */
    public void saveUserInfo(Integer hotelId,String cardId,String code,Map resultMap){
        String openId = resultMap.get("openid").toString();
        UserInfo userInfo = userInfoDao.findByOpenId(openId);
        if(userInfo == null) {
            userInfo = new UserInfo();
            String nickname = resultMap.get("nickname").toString();
            String membership_number = resultMap.get("membership_number").toString();
            //积分信息
            Integer bonus = Integer.parseInt(resultMap.get("bonus").toString());
            userInfo.setOpenId(openId);
            userInfo.setScore(bonus);
            userInfo.setNickName(nickname);
            userInfo.setCardNum(membership_number);
            userInfo.setCardCode(code);
            userInfo.setRegisterTime(DateUtils.getNowTime());
            userInfo.setCardId(cardId);
            userInfo.setLuckDraw(1);
            Map<String, List> user_info = (Map<String, List>) resultMap.get("user_info");
            List list = user_info.get("common_field_list");
            for (int i = 0; i < list.size(); i++) {
                Map userMap = (Map) list.get(i);
                if (userMap.get("name").toString().equals("USER_FORM_INFO_FLAG_MOBILE")) {
                    String phone = userMap.get("value").toString();
                    userInfo.setPhone(phone);
                }
                if (userMap.get("name").toString().equals("USER_FORM_INFO_FLAG_NAME")) {
                    String name = userMap.get("value").toString();
                    userInfo.setName(name);
                }
                if (userMap.get("name").toString().equals("USER_FORM_INFO_FLAG_BIRTHDAY")) {
                    String birthday = userMap.get("value").toString();
                    userInfo.setBirday(birthday);
                }
                if (userMap.get("name").toString().equals("USER_FORM_INFO_FLAG_SEX")) {
                    String sex = userMap.get("value").toString();
                    userInfo.setGender(sex);
                }
            }
            userInfoDao.save(userInfo);
            UserIntegral userIntegral = new UserIntegral();
            userIntegral.setUserId(userInfo.getId());
            userIntegral.setOpenId(userInfo.getOpenId());
            userIntegral.setPhone(userInfo.getPhone());
            userIntegral.setChangeScore(bonus);
            userIntegral.setCreateTime(DateUtils.getNowTime());
            userIntegral.setChangeType(0);
        }

    }
    /**
     * 获取在该公众号下的用户会员卡信息
     *
     * @return
     */
    public ApiResponse<Map<String,String>> getCardList(Integer hotelId,String openId){
        try {
            ConfWxmp confWxmp = confWxmpDao.findByBusId(hotelId);
            RuntimeCheck.ifNull(confWxmp,"该业务信息未配置");
            final WxMpService wxMpService = WxMpConfiguration.getMpService(confWxmp.getAppId());
            JSONObject jsonParam = new JSONObject();
            jsonParam.put("openid", openId);
            jsonParam.put("card_id","");
            String param = jsonParam.toJSONString();
            logger.info("getCardList----------请求参数---------"+param);
            String result = wxMpService.post(GET_CARD_LIST,param);
            Map resultMap = JsonUtil.toMap(result);
            if((int)resultMap.get("errcode") == 0){
                 List<Map<String,String>> cardList = (List) resultMap.get("card_list");
                return ApiResponse.success(cardList.get(0));
            }
//            wxMpCardService.cardL
        } catch (WxErrorException e) {
            e.printStackTrace();
            logger.error("微信接口获取用户会员卡信息有误",e);
            return ApiResponse.fail(new HashMap<String,String>());

        }
        return null;
    }
    public WxMpService getMpService(Integer hotelId){
        ConfWxmp confWxmp = confWxmpDao.findByBusId(hotelId);
        RuntimeCheck.ifNull(confWxmp,"该业务信息未配置");
        final WxMpService wxMpService = WxMpConfiguration.getMpService(confWxmp.getAppId());
        return wxMpService;
    }
    public String uploadLogo(String accessToken,String filePath){
        try {
//            String accessToken = wxMpService.getAccessToken();//获取到token

            // 上传文件请求路径
            String action = "http://api.weixin.qq.com/cgi-bin/media/uploadimg?access_token="
                    + accessToken ;

            URL url = new URL(action);
            String result = null;
            File file = new File(filePath);
            if (!file.exists() || !file.isFile()) {
                throw new IOException("上传的文件不存在");
            }
            HttpURLConnection con = (HttpURLConnection) url.openConnection();
            con.setRequestMethod("POST"); // 以Post方式提交表单，默认get方式
            con.setDoInput(true);
            con.setDoOutput(true);
            con.setUseCaches(false); // post方式不能使用缓存

            // 设置请求头信息
            con.setRequestProperty("Connection", "Keep-Alive");
            con.setRequestProperty("Charset", "UTF-8");
            // 设置边界
            String BOUNDARY = "----------" + System.currentTimeMillis();
            con.setRequestProperty("Content-Type", "multipart/form-data; boundary="
                    + BOUNDARY);

            // 请求正文信息
            // 第一部分：
            StringBuilder sb = new StringBuilder();
            sb.append("--"); // 必须多两道线
            sb.append(BOUNDARY);
            sb.append("\r\n");
            sb.append("Content-Disposition: form-data;name=\"file\";filename=\""
                    + file.getName() + "\"\r\n");
            sb.append("Content-Type:application/octet-stream\r\n\r\n");
            byte[] head = sb.toString().getBytes("utf-8");
            // 获得输出流
            OutputStream out = new DataOutputStream(con.getOutputStream());

            // 输出表头
            out.write(head);
            // 文件正文部分
            // 把文件已流文件的方式 推入到url中
            DataInputStream in = new DataInputStream(new FileInputStream(file));
            int bytes = 0;
            byte[] bufferOut = new byte[1024];
            while ((bytes = in.read(bufferOut)) != -1) {
                out.write(bufferOut, 0, bytes);
            }
            in.close();

            // 结尾部分
            byte[] foot = ("\r\n--" + BOUNDARY + "--\r\n").getBytes("utf-8");// 定义最后数据分隔线
            out.write(foot);
            out.flush();
            out.close();
            StringBuffer buffer = new StringBuffer();
            BufferedReader reader = null;

            try {
                // 定义BufferedReader输入流来读取URL的响应
                reader = new BufferedReader(new InputStreamReader(con
                        .getInputStream()));
                String line = null;
                while ((line = reader.readLine()) != null) {
                    buffer.append(line);
                }
                if (result == null) {
                    result = buffer.toString();
                }
            } catch (IOException e) {
                System.out.println("发送POST请求出现异常！" + e);
                e.printStackTrace();
                throw new IOException("数据读取异常");
            } finally {
                if (reader != null) {
                    reader.close();
                }
            }
            return result;
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }



    public  String post(String url,String content) {
        String line         = "";
        String message        = "";
        String returnData   = "";
        boolean postState     = false;
        BufferedReader bufferedReader = null;

        try {
            URL urlObject = new URL(url);
            HttpURLConnection urlConn = (HttpURLConnection) urlObject.openConnection();
            urlConn.setDoOutput(true);
            /*设定禁用缓存*/
            urlConn.setRequestProperty("Cache-Control", "no-cache");
            /*维持长连接*/
            urlConn.setRequestProperty("Connection", "Keep-Alive");
            /*设置字符集*/
            urlConn.setRequestProperty("Charset", "UTF-8");
            /*设定输出格式为json*/
            urlConn.setRequestProperty("Content-Type", "application/json;charset=utf-8");
            /*设置使用POST的方式发送*/
            urlConn.setRequestMethod("POST");
            /*设置不使用缓存*/
            urlConn.setUseCaches(false);
            /*设置容许输出*/
            urlConn.setDoOutput(true);
            /*设置容许输入*/
            urlConn.setDoInput(true);
            urlConn.connect();

            OutputStreamWriter outStreamWriter = new OutputStreamWriter(urlConn.getOutputStream(),"UTF-8");
            outStreamWriter.write(content);
            outStreamWriter.flush();
            outStreamWriter.close();

            /*若post失败*/
            if((urlConn.getResponseCode() != 200)){
                returnData = "{\"jsonStrStatus\":0,\"processResults\":[]}";
                message = "发送POST失败！"+ "code="+urlConn.getResponseCode() + "," + "失败消息："+ urlConn.getResponseMessage();
                // 定义BufferedReader输入流来读取URL的响应
                InputStream errorStream = urlConn.getErrorStream();

                if(errorStream != null)
                {
                    InputStreamReader inputStreamReader = new InputStreamReader(errorStream,"utf-8");
                    bufferedReader = new BufferedReader(inputStreamReader);

                    while ((line = bufferedReader.readLine()) != null) {
                        message += line;
                    }
                    inputStreamReader.close();
                }
                errorStream.close();
                System.out.println("发送失败！错误信息为："+message);
            }else{
                /*发送成功返回发送成功状态*/
                postState = true;

                // 定义BufferedReader输入流来读取URL的响应
                InputStream inputStream = urlConn.getInputStream();

                InputStreamReader inputStreamReader = new InputStreamReader(inputStream,"utf-8");
                bufferedReader = new BufferedReader(inputStreamReader);

                while ((line = bufferedReader.readLine()) != null) {
                    message += line;
                }
                returnData = message;
                inputStream.close();
                inputStreamReader.close();

                System.out.println("发送POST成功！返回内容为：" + returnData);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            try {
                if (bufferedReader != null) {
                    bufferedReader.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
            return returnData;
        }
    }

}
